#ifndef _LOG_H_
#define _LOG_H_

#include <stdio.h>
#include <stdlib.h>

#include <pthread.h>

/** 日志等级 */
typedef enum
{
    LOG_LEVEL_CUSTOM = 0, /**< 自定义级别，将日志打上自定义标记 */
    LOG_LEVEL_EMERG,
    LOG_LEVEL_ALERT,
    LOG_LEVEL_CRITICAL,
    LOG_LEVEL_ERROR,
    LOG_LEVEL_WARNING,
    LOG_LEVEL_NOTICE,
    LOG_LEVEL_INFO,
    LOG_LEVEL_DEFAULT
} LOG_LEVEL;

/** 日志处理标识 */
typedef enum
{
    LSF_PRINT, /**< 输出到终端 */
    LSF_FLASH, /**< 保存到文件 */
    LSF_FULL   /**< 即输出到终端也保存到文件 */
} LOG_SAVE_FLAG;

#define LOG_SIZE 4096
#define LOG_FILE_LEN 256
typedef struct
{
    char filename[LOG_FILE_LEN];
    char saved;
    char logBuff[LOG_SIZE];
    LOG_LEVEL level;
    FILE *fp;
    pthread_mutex_t log_metex;
} log_t;

#define LOG_CUSTOM(tag, log_type_p, format, ...) log_print(__FILE__, __LINE__, LOG_LEVEL_CUSTOM, log_type_p, tag, format, ##__VA_ARGS__)
#define LOG_DEFAULT(log_type_p, format, ...) log_print(__FILE__, __LINE__, LOG_LEVEL_DEFAULT, log_type_p, NULL, format, ##__VA_ARGS__)
#define LOG_INFO(log_type_p, format, ...) log_print(__FILE__, __LINE__, LOG_LEVEL_INFO, log_type_p, NULL, format, ##__VA_ARGS__)
#define LOG_NOTICE(log_type_p, format, ...) log_print(__FILE__, __LINE__, LOG_LEVEL_NOTICE, log_type_p, NULL, format, ##__VA_ARGS__)
#define LOG_WARNING(log_type_p, format, ...) log_print(__FILE__, __LINE__, LOG_LEVEL_WARNING, log_type_p, NULL, format, ##__VA_ARGS__)
#define LOG_ERROR(log_type_p, format, ...) log_print(__FILE__, __LINE__, LOG_LEVEL_ERROR, log_type_p, NULL, format, ##__VA_ARGS__)
#define LOG_CRITICAL(log_type_p, format, ...) log_print(__FILE__, __LINE__, LOG_LEVEL_CRITICAL, log_type_p, NULL, format, ##__VA_ARGS__)
#define LOG_ALERT(log_type_p, format, ...) log_print(__FILE__, __LINE__, LOG_LEVEL_ALERT, log_type_p, NULL, format, ##__VA_ARGS__)
#define LOG_EMERG(log_type_p, format, ...) log_print(__FILE__, __LINE__, LOG_LEVEL_EMERG, log_type_p, NULL, format, ##__VA_ARGS__)

extern __inline void log_print(const char *filename, int line, LOG_LEVEL level, log_t *log_type, const char *tag, char *format, ...);

extern log_t *log_init(const char *logfile, LOG_SAVE_FLAG saveFlag, LOG_LEVEL level);

extern void log_destroy(log_t *log_type);
#endif